package com.hw.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

/**
 * NIO 的客户端程序
 * selector多路复用模式下必须设置channel为非阻塞
 * @program: NIO_Netty
 * @description:
 * @author: hewei
 * @date: 2023-03-31 11:38
 **/
public class SelectChannelClient {
    private static ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
    private static Charset charset = Charset.forName("UTF-8");

    public static void main(String[] args) throws IOException {
        try (SocketChannel socketChannel = SocketChannel.open()){
            socketChannel.configureBlocking(false);
            Selector selector=Selector.open();
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            socketChannel.connect(new InetSocketAddress("localhost",9696));
            while (selector.select() > 0) {
                Iterator<SelectionKey> iterator=selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    executeEvent(selector,iterator.next());
                    iterator.remove();
                }
            }
        }
    }

    public static void executeEvent(Selector selector, SelectionKey key) throws IOException {
        Long timestamp=System.currentTimeMillis();
        if (key.isConnectable()) {
            SocketChannel channel = (SocketChannel) key.channel();
            if (channel.isConnectionPending()) {channel.finishConnect();}
            System.out.println("Client Connected - "+timestamp+" : "+channel.getRemoteAddress());
            channel.register(selector,SelectionKey.OP_READ);
        }else if (key.isReadable()){
            SocketChannel channel = (SocketChannel) key.channel();
            channel.read(buffer);
            /*读写模式转换*/
            buffer.flip();
            System.out.println("Client received："+"["+channel.getRemoteAddress()+"]"+ charset.decode(buffer));
            buffer.clear();
            channel.register(selector,SelectionKey.OP_WRITE);
        }else if (key.isWritable()){
            SocketChannel channel = (SocketChannel) key.channel();
            buffer.put(new String("你好，这是客户端:"+timestamp).getBytes(StandardCharsets.UTF_8));
            buffer.flip();
            channel.write(buffer);
            System.out.println("Client send：你好，这是客户端!");
            buffer.clear();
            channel.register(selector,SelectionKey.OP_READ);
        }
    }
}
